/*!	 valuenode_registry.cpp
**	 Valuenode automatic registry
**
**	Copyright (c) 2016 caryoscelus
**
**	This package is free software; you can redistribute it and/or
**	modify it under the terms of the GNU General Public License as
**	published by the Free Software Foundation; either version 2 of
**	the License, or (at your option) any later version.
**
**	This package is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**	General Public License for more details.
**
*/

#include "valuenode_registry.h"

#include "general.h"
#include "localization.h"

using namespace synfig;

ValueNodeRegistry::Book* ValueNodeRegistry::book_ = NULL;

ValueNodeRegistry::Book&
ValueNodeRegistry::book()
{
    if (!book_) {
        book_ = new Book();
    }

    return *book_;
}

String
ValueNodeRegistry::localize_name(const String &local_name)
{
    return _(local_name.c_str());
}

void
ValueNodeRegistry::register_node_type(const String &name, const String &local_name, ReleaseVersion version, Factory factory, CheckType check_type)
{
    book()[name].local_name = local_name;
    book()[name].release_version = version;
    book()[name].factory = factory;
    book()[name].check_type = check_type;
}

bool
ValueNodeRegistry::cleanup()
{
    if (book_) {
        delete book_;
        book_ = NULL;
    }

    return true;
}

LinkableValueNode::Handle
ValueNodeRegistry::create(const String &name, const ValueBase& x)
{
    // forbid creating a node if class is not registered
    if (!ValueNodeRegistry::book().count(name)) {
        return NULL;
    }

    if (!check_type(name, x.get_type())) {
        error(_("Bad type: ValueNode '%s' doesn't accept type '%s'"), ValueNodeRegistry::book()[name].local_name.c_str(), x.get_type().description.local_name.c_str());
        return NULL;
    }

    return ValueNodeRegistry::book()[name].factory(x, NULL);
}

bool
ValueNodeRegistry::check_type(const String &name, Type &x)
{
    // the BoneRoot and Duplicate ValueNodes are exceptions - we don't want the
    // user creating them for themselves, so check_type() fails for
    // them even when it is valid
    if ((name == "bone_root" && x == type_bone_object) ||
            (name == "duplicate" && x == type_real)) {
        return true;
    }

    if (!ValueNodeRegistry::book().count(name) || !ValueNodeRegistry::book()[name].check_type) {
        return false;
    }

    return ValueNodeRegistry::book()[name].check_type(x);
}